#ifndef __FLASH_H
#define __FLASH_H

#include "hc32f460.h"
#include <rtthread.h>
#include <rtdevice.h>
#include "board_config.h"
#include <string.h>
#include <rtdef.h>
#include "anv_leaks.h"

#define ENABLE_FCG0_REG_WRITE()             (M4_MSTP->FCG0PC = 0xa5a50001u)
#define DISABLE_FCG0_REG_WRITE()            (M4_MSTP->FCG0PC = 0xa5a50000u)

/****************************************/
#define FLASH_SPI_BUS_NAME         "spi1"
#define FLASH_SPI_DEVICE_NAME      "spi10"

#define FLASH_SPI1_CS_PORT                (GPIO_PORT_A)
#define FLASH_SPI1_CS_PIN                 (GPIO_PIN_06)
                     
#define FLASH_SPI1_SCK_PORT               (GPIO_PORT_C)
#define FLASH_SPI1_SCK_PIN                (GPIO_PIN_05)
#define FLASH_SPI1_SCK_FUNC               (Func_Spi1_Sck)
                     
#define FLASH_SPI1_MOSI_PORT              (GPIO_PORT_C)
#define FLASH_SPI1_MOSI_PIN               (GPIO_PIN_04)
#define FLASH_SPI1_MOSI_FUNC              (Func_Spi1_Mosi)
                     
#define FLASH_SPI1_MISO_PORT              (GPIO_PORT_A)
#define FLASH_SPI1_MISO_PIN               (GPIO_PIN_07)
#define FLASH_SPI1_MISO_FUNC              (Func_Spi1_Miso)

#define SPI1_CS_PORT_PIN        FLASH_SPI1_CS_PORT , FLASH_SPI1_CS_PIN   //  GET_PIN(A, 8)
#define SPI1_CS_PPIN            GET_PIN(A, 6)
#define SPI1_SCK_PIN            FLASH_SPI1_SCK_PORT , FLASH_SPI1_SCK_PIN   //GET_PIN(A, 9)
#define SPI1_MOSI_PIN           FLASH_SPI1_MOSI_PORT , FLASH_SPI1_MOSI_PIN  //GET_PIN(C, 9)
#define SPI1_MISO_PIN           FLASH_SPI1_MISO_PORT , FLASH_SPI1_MISO_PIN  //GET_PIN(A, 10)

#define FLASH_THREAD_STACK_SIZE 2048

//最大允许写入重试次数
#define FLASH_MAX_WRITE_COUNT	4
//一页大小
#define GD25Q64C_PAGE_SIZE	256

#define SECTOR_SIZE  		4096
/************ 命令定义 ************/
//Enable wirte
#define GD25Q64C_CMD_WREN		0x06
//Disable wite
#define GD25Q64C_CMD_WRDI		0x04
//Read Status Register
#define GD25Q64C_CMD_RDSR		0x05 //0x05-S0:S7 or 0x35-S8:S15 or 0x15-S16:S23  
//Write Status Register
#define GD25Q64C_CMD_WRSR		0x01 //0x01-S0:S7 or 0x31-S8:S15 or 0x11-S16:S23 
//Read Data Bytes
#define GD25Q64C_CMD_READ		0x13  //0x03
//Read Data Bytes at Higher Speed
#define GD25Q64C_CMD_FREAD		0x0C //0x0B
//Page Program
#define GD25Q64C_CMD_PP			0x12  //0x02
//Sector Erase
#define	GD25Q64C_CMD_SE			0x21 //0x20
//32KB Block Erase
#define GD25Q64C_CMD_32BE		0x5C //0x52
//64KB Block Erase
#define GD25Q64C_CMD_64BE		0xDC //0xD8
//Chip Erase(CE)
#define GD25Q64C_CMD_CE			0x60 //or 0xC7
//Enable Reset
#define GD25Q64C_CMD_ER			0x66
//Reset
#define GD25Q64C_CMD_RE			0x99
//four bit
#define GD25Q64C_CMD_Four       0xB7
/**********************************************Flash定义******************************************************/                          
#define CS_SPI_RESET_161            1
#define CS_SPI_256401               10
#define CS_SPI_256402               11
#define CS_SPI_FLASH                12              //指Flash芯片
#define CS_SPI_SAMPLE               23
#define CS_SPI_SAMPLE_DATA          24
#define CS_SPI_ESAM               	30
// Flash 操作类型
typedef enum {
    FLASH_OP_ERASE,
    FLASH_OP_WRITE,
    FLASH_OP_READ,
    FLASH_OP_VERIFY
} flash_op_t;
// Flash 操作请求结构
typedef struct {
    flash_op_t op_type;
    rt_uint32_t addr;
    rt_uint32_t size;
    void *data;
    rt_sem_t completion_sem;
    rt_err_t result;
} flash_req_t;
    
extern rt_mq_t flash_mq;
extern rt_device_t Flashdev;
extern struct rt_spi_device * spi_dev;


void Flash_thread_entry(void *parameter);
rt_err_t flash_write_sync(rt_uint32_t addr, const void *data, rt_uint32_t size);
rt_err_t flash_Read_sync(rt_uint32_t addr, const void *data, rt_uint32_t size);
bool ReadExtFlash(uint16_t No, uint32_t Addr, uint16_t Len, uint8_t * pBuf);
bool WriteExtFlash( uint8_t No, uint32_t Addr, uint16_t Len, uint8_t *pBuf );
int filesystem_mount(void);
#endif